package com.tanhua.sso.service;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tanhua.common.mapper.UserMapper;
import com.tanhua.common.pojo.User;

import com.tanhua.dubbo.server.api.HuanXinApi;
import com.tanhua.sso.vo.Result;
import com.tanhua.sso.vo.rediskey;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Value("${jwt.secret}")
    private String secret;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Reference(version = "1.0.0",check =false)
    private HuanXinApi huanXinApi;
    public String login(String phone, String code) {
        String redisKey = "CHECK_CODE_" + phone;
        boolean isNew = false;

        //校验验证码
        String redisData = this.redisTemplate.opsForValue().get(redisKey);
        if (!StringUtils.equals(code, redisData)) {
            return null; //验证码错误
        }

        //验证码在校验完成后，需要废弃
        this.redisTemplate.delete(redisKey);

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", phone);

        User user = this.userMapper.selectOne(queryWrapper);

        if (null == user) {
            //需要注册该用户
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456"));

            //注册新用户
            this.userMapper.insert(user);
            isNew = true;

            // 将该用户信息注册到环信平台
            // 调用Dubbo实现环信的注册  用户名  密码  昵称
            Boolean register = this.huanXinApi.register(user.getId());
            if (!register) {
                log.error("注册到环信平台失败！ " + user.getId());
            }
        }

        //生成token
        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put("id", user.getId());

        // 生成token
        String token = Jwts.builder()
                .setClaims(claims) //payload，存放数据的位置，不能放置敏感数据，如：密码等
                .signWith(SignatureAlgorithm.HS256, secret) //设置加密方法和加密盐
                .setExpiration(new DateTime().plusHours(12).toDate()) //设置过期时间，12小时后过期
                .compact();

        try {
            //发送用户登录成功的消息
            Map<String, Object> msg = new HashMap<>();
            msg.put("id", user.getId());
            msg.put("date", System.currentTimeMillis());

            this.rocketMQTemplate.convertAndSend("tanhua-sso-login", msg);
        } catch (MessagingException e) {
            log.error("发送消息失败！", e);
        }

        return token + "|" + isNew;
    }
    public User findUserbytoken(String token) {
        try {
            Map<String, Object> body = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
            User user = new User();
            user.setId(Long.valueOf(body.get("id").toString()));
            String key = rediskey.mobile+user.getId();
            if (redisTemplate.hasKey(key)) {
                String mobile = redisTemplate.opsForValue().get(key);
                user.setMobile(mobile);
            }else{
                User user1 = userMapper.selectById(user.getId());
                user.setMobile(user1.getMobile());
                Long timeout= Long.valueOf(body.get("exp").toString())*1000- System.currentTimeMillis();
                redisTemplate.opsForValue().set(key,user1.getMobile(),timeout, TimeUnit.MILLISECONDS);
            }return user;
        } catch (ExpiredJwtException e){
            log.error("您的token已经过期了token="+token);
        }
        catch (Exception e) {
           log.error("您的token不合法token="+token,e);
        }return null;
    }

    public Result sendCheckCode(String phone) {
        boolean matches = phone.matches("^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$");
        if(!matches){
            return Result.builder().code("1002").msg("手机号码有误").build();
        }
        String redisKey = "CHECK_CODE_" + phone;
        if(this.redisTemplate.hasKey(redisKey)){
            String msg = "上一次发送的验证码还未失效！";
            return Result.builder().code("000001").msg(msg).build();
        }

//        String code = this.sendSms(phone);
        String code = "123456";

        if(StringUtils.isEmpty(code)){
            String msg = "发送短信验证码失败！";
            return Result.builder().code("000000").msg(msg).build();
        }

        //短信发送成功，将验证码保存到redis中，有效期为5分钟
        this.redisTemplate.opsForValue().set(redisKey, code, Duration.ofMinutes(5));

        return null;
    }
    public Boolean updatePhone(Long userId, String newPhone) {
        //先查询新手机号是否已经注册，如果已经注册，就不能修改
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", newPhone);
        // 使用新手机号码去查询User
        User user = this.userMapper.selectOne(queryWrapper);

        if(ObjectUtil.isNotEmpty(user)){
            // 新手机号已经被注册
            return false;
        }

        user = new User();
        user.setId(userId);
        user.setMobile(newPhone);// 新手机号码
        // 根据用户的ID更新手机号码到数据库
        return this.userMapper.updateById(user) > 0;
    }
    }
